﻿using Surging.Core.System.Module;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.Hosting;
using Servicecomb.Saga.Omega.Core.Transport.AspNetCore;
using Servicecomb.Saga.Omega.Core.Serializing;
using Servicecomb.Saga.Omega.Abstractions.Transaction;
using Servicecomb.Saga.Omega.Abstractions.Diagnostics;
using Servicecomb.Saga.Omega.Abstractions.Logging;
using Servicecomb.Saga.Omega.Core.Context;
using Servicecomb.Saga.Omega.Abstractions.Context;
using Servicecomb.Saga.Omega.Core.Transaction.Impl;
using Servicecomb.Saga.Omega.Core.Connector.GRPC;
using Servicecomb.Saga.Omega.Protocol;
using Grpc.Core;
using Autofac;
using Servicecomb.Saga.Omega.Core.Diagnostics;
using JetBrains.Annotations;
using Servicecomb.Saga.Omega.Core.Transport.Rpc;
using Surging.Core.CPlatform.Module;
using ContainerBuilderWrapper = Surging.Core.CPlatform.Module.ContainerBuilderWrapper;
using Servicecomb.Saga.Omega.Abstractions.Transaction.Extensions;
using System.Threading;

namespace Servicecomb.Saga.Omega.AspNetCore.Extensions
{
    public class OmegaModule : EnginePartModule
    {
        /// <summary>
        ///  Function module initialization,trigger when the module starts loading
        /// </summary>
        public override void Initialize(AppModuleContext context) //Trigger when the module starts loading
        {
            base.Initialize(context);
            var hostService = ServiceLocator.Current.GetInstance<IHostedService>();
             hostService.StartAsync(new CancellationToken() { });

        }

        /// <summary>
        /// Inject dependent third-party components
        /// </summary>
        /// <param name="builder"></param>
        protected override void RegisterBuilder(ContainerBuilderWrapper builder)
        
        {
            base.RegisterBuilder(builder);
            builder.RegisterType<OmegaHostedService>().As<IHostedService>().SingleInstance();
            builder.RegisterType<JsonMessageFormat>().As<IMessageSerializer>().SingleInstance();
            builder.RegisterType<HostingDiagnosticIntercept>().As<IDiagnosticItercept>().SingleInstance();
            builder.RegisterType<NullLoggerFactory>().As<ILoggerFactory>().SingleInstance();
            builder.RegisterType(typeof(UniqueIdGenerator)).As(typeof(IIdGenerator<string>)).SingleInstance();
            builder.RegisterType<DefaultRecovery>().As<IRecoveryPolicy>().SingleInstance();
            builder.RegisterType(typeof(OmegaContext)).SingleInstance();
            builder.RegisterType(typeof(CompensationContext)).SingleInstance();
            builder.RegisterType(typeof(SagaStartAttribute)).SingleInstance();
            builder.RegisterType(typeof(CompensableAttribute)).SingleInstance();

            var option = new OmegaOptions()
            {
                GrpcServerAddress = "localhost:8080",
                InstanceId = "Car123",
                ServiceName = "Car"
            };

            builder.RegisterInstance<IMessageSender>(new GrpcClientMessageSender(
                new GrpcServiceConfig
                {
                    InstanceId = option.InstanceId,
                    ServiceName = option.ServiceName
                },
                new Channel(option.GrpcServerAddress, ChannelCredentials.Insecure),
                new JsonMessageFormat(),
                option.GrpcServerAddress
                )).SingleInstance();

            builder.RegisterType<SagaStartAnnotationProcessor>().As<IEventAwareInterceptor>().SingleInstance();
            builder.RegisterType<CompensableInterceptor>().As<IEventAwareInterceptor>().SingleInstance();
            builder.Register<ISagaStartEventAwareInterceptor>(provider =>
            {
                return new SagaStartAnnotationProcessor(provider.Resolve<OmegaContext>(), provider.Resolve<IMessageSender>());
            }).SingleInstance();
            AddDiagnostics(builder).AddRpcClient(builder);



        }


        public OmegaModule AddDiagnostics(ContainerBuilderWrapper builder)
        {
            builder.RegisterType(typeof(DiagnosticListenerObserver)).SingleInstance();
            return this;
        }

        public OmegaModule AddRpcClient([NotNull]ContainerBuilderWrapper builder)
        {
            builder.RegisterType<RpcClientDiagnosticIntercept>().As<IDiagnosticItercept>().SingleInstance();

            return this;
        }


    }
}
